#include "util.h"
#include <windows.h>
#include "tinyxml/tinystr.h"
#include "tinyxml/tinyxml.h"
#include "hge.h"
#include <map>
#include "hgeheader.h"

extern HGE *hge;
extern GfxFont *font;
wchar_t * MBToWChar( const char *str )
{
    static wchar_t temp[1024];
    temp[0] = 0;
    int converted = ::MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, str, -1, temp, 1024 );
    return temp;
}

char * WCharToMB( const wchar_t *str )
{
    static char temp[1024];
    temp[0] = 0;
    int converted = ::WideCharToMultiByte( CP_ACP, WC_NO_BEST_FIT_CHARS | WC_COMPOSITECHECK, str, -1, temp, 1024, NULL, NULL );
    return temp;
}

int atoi_s( const char* str, int defaultv  )
{
    if(str == NULL)
        return defaultv;
    else
        return atoi(str);
}

__int64 atoi64_s( const char* str, int defaultv )
{
    if(str == NULL)
        return defaultv;
    else
        return _atoi64(str);
}

float atof_s( const char* str, float defaultv)
{
    if(str == NULL)
        return defaultv;
    else
        return (float)atof(str);
}

float GetXmlFloat( TiXmlElement *pElement, const char *nodeName, float defaultv )
{
    if( pElement == NULL || nodeName == NULL )
        return defaultv;
    TiXmlElement *pChild = pElement->FirstChildElement(nodeName);
    if( pChild == NULL )
        return defaultv;
    return atof_s( pChild->GetText() );
}

int GetXmlInteger( TiXmlElement *pElement, const char *nodeName, int defaultv  )
{
    if( pElement == NULL || nodeName == NULL )
        return defaultv;
    TiXmlElement *pChild = pElement->FirstChildElement(nodeName);
    if( pChild == NULL )
        return defaultv;
    return atoi_s( pChild->GetText() );
}

__int64 GetXmlInt64( TiXmlElement *pElement, const char *nodeName, int defaultv )
{
    if( pElement == NULL || nodeName == NULL )
        return defaultv;
    TiXmlElement *pChild = pElement->FirstChildElement(nodeName);
    if( pChild == NULL )
        return defaultv;
    return atoi64_s( pChild->GetText() );
}

const char* GetXmlString( TiXmlElement *pElement, const char *nodeName, const char *defaultv  )
{
    if( pElement == NULL || nodeName == NULL )
        return defaultv;
    TiXmlElement *pChild = pElement->FirstChildElement(nodeName);
    if( pChild == NULL || pChild->GetText() == NULL )
        return defaultv;
    return pChild->GetText();
}

void renderRectangle( float x1, float y1, float x2, float y2, int color,bool solid, float z )
{
    if(solid)
    {
        hgeVertex ver[] = 
        {
            {x1, y1, z, color, 0, 0},
            {x2, y1, z, color, 0, 0},
            {x2, y2, z, color, 0, 0},
            {x1, y2, z, color, 0, 0},
        };
        hgeQuad quad;
        memcpy(quad.v, ver, sizeof(ver));
        quad.blend = BLEND_DEFAULT;
        quad.tex = 0;
        hge->Gfx_RenderQuad(&quad);
    }
    else
    {
        hge->Gfx_RenderLine(x1,y1,x2,y1,color,z);
        hge->Gfx_RenderLine(x1,y1,x1,y2,color,z);
        hge->Gfx_RenderLine(x2,y1,x2,y2,color,z);
        hge->Gfx_RenderLine(x1,y2,x2,y2,color,z);
    }
}

void renderTriangle( float x1, float y1, float x2, float y2, float x3, float y3, int color /*= 0xff000000*/, bool solid /*= false*/, float z/*=0.5f*/ )
{
	if(solid)
	{
		hgeVertex ver[] = 
		{
			{x1, y1, z, color, 0, 0},
			{x2, y2, z, color, 0, 0},
			{x3, y3, z, color, 0, 0},
		};
		hgeTriple triple;
		memcpy(triple.v, ver, sizeof(ver));
		triple.blend = BLEND_DEFAULT;
		triple.tex = 0;
		hge->Gfx_RenderTriple(&triple);
	}
	else
	{
		hge->Gfx_RenderLine(x1,y1,x2,y2,color,z);
		hge->Gfx_RenderLine(x2,y2,x3,y3,color,z);
		hge->Gfx_RenderLine(x3,y3,x1,y1,color,z);
	}
}

int loadTexture( std::string filename )
{
    static std::map<std::string, int> texmap;
    std::map<std::string, int>::iterator iter = texmap.find( filename );
    if( iter != texmap.end() )
    {
        return iter->second;
    }
    else
    {
        int texid = (int) hge->Texture_Load(filename.c_str());
        if( texid != 0 )
            texmap[filename] = texid;
        return texid;
    }
}

void showDialog( const char *content )
{
    while(true)
    {
        hge->Gfx_BeginScene();
        hge->Gfx_Clear(0xFFFFFFFF);
        renderRectangle(0,0,100,100);
        font->Print(10,10,"%s",content);
        hge->Gfx_EndScene();
        Sleep(1);
    }
}

const char * easyitoa( int i )
{
    static char buf[65];
    _itoa(i,buf,10);
    return buf;
}

void WriteString( std::ofstream &f, std::string &s )
{
    int size = s.length();
    f.write((char*)&size, sizeof(size));
    f.write(s.c_str(),size);
}

void ReadString( std::ifstream &f, std::string &s )
{
    int size = 0;
    f.read((char *)&size,sizeof(size));
    char str[1024];
    f.read(str,size);
    str[size]=0;
    s=str;
}

void splitToVector( const char *str, std::vector<int>& vec )
{
    if( str==NULL || strlen(str)==0 )
        return;
    while( str[0]==' ')
        str++; 
    vec.push_back(atoi(str));
    return splitToVector(strstr(str," "),vec);
}

void splitToMap( const char *str, std::map<int,int>& m )
{
    if( str==NULL || strlen(str)==0 )
        return;
    while( str[0]==' ')
        str++; 
    int key = atoi(str);
    str = strstr(str,":");
    if( str==NULL || strlen(str)==0 )
        return;
    str++;
    int value = atoi(str);
    m[key] = value;
    return splitToMap(strstr(str," "),m);
}

const char * GeneratePath( const char *pathtype, const char *filename )
{
	static char temp[256];
	strcpy( temp, filename );
	if( strcmp(pathtype, "animation")==0 )
	{
		sprintf( temp, "data\\animation\\%s.anim",filename);
	}
	else if( strcmp(pathtype, "config")==0 )
	{
		sprintf( temp, "data\\%s",filename);
	}
	return temp;
}

void PushGameStack( renderfunc render, framefunc frame )
{
	renders.push_back(render);
	frames.push_back(frame);
}

void PopGameStack()
{
	renders.pop_back();
	frames.pop_back();
}

void renderCursor()
{
	float x,y = 0.0f;
	hge->Input_GetMousePos(&x, &y);
	cursor->Render( x, y );
}
